package com.hitqz.robot.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hitqz.robot.api.business.dto.RobotClientDevicePosDto;
import com.hitqz.robot.api.business.enums.RobotOtherCommandEnum;
import com.hitqz.robot.api.business.model.param.roboMapPos.QueryMapPosParams;
import com.hitqz.robot.api.business.model.vo.robotMapPos.PosMarkVo;
import com.hitqz.robot.api.business.model.vo.robotMapPos.RobotMapPosVo;
import com.hitqz.robot.api.common.entity.RobotMap;
import com.hitqz.robot.api.common.entity.RobotMapPos;
import com.hitqz.robot.biz.business.dispatch.DispatchService;
import com.hitqz.robot.biz.service.RobotMapPosService;
import com.hitqz.robot.biz.service.RobotMapService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.driver.model.IRobotPosDto;
import com.hitqz.robot.driver.parent.RobotDriverService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xupkun
 * @date 2024/5/29
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/robotMapPos")
@Tag(name = "地图点位")
public class RobotMapPosController {

    private final RobotMapPosService robotMapPosService;

    private final RobotDriverService robotDriverService;

    private final RobotService robotService;

    private final RobotMapService robotMapService;

    private final DispatchService dispatchService;

    @PostMapping("/page")
    @Operation(summary = "分页查询地图点位数据")
    public R<Page<RobotMapPosVo>> page(@RequestBody QueryMapPosParams queryMapPosParams) {
        Map<String, String> codeNameMap = robotMapService.list().stream().collect(Collectors.toMap(RobotMap::getMapCode, RobotMap::getMapName));
        Page page = new Page<>(queryMapPosParams.getCurrent(),queryMapPosParams.getSize());
        Page<RobotMapPos> data = robotMapPosService.page( page,
                Wrappers.<RobotMapPos>lambdaQuery()
                        .eq(StrUtil.isNotBlank(queryMapPosParams.getMapCode()), RobotMapPos::getMapCode,queryMapPosParams.getMapCode())
                        .like(StrUtil.isNotBlank(queryMapPosParams.getName()), RobotMapPos::getName, queryMapPosParams.getName()));
        Page<RobotMapPosVo> voPage = new Page<>();
        BeanUtil.copyProperties(data, voPage, false);//复制页码等信息
        List<RobotMapPosVo> voList = BeanUtil.copyToList(data.getRecords(), RobotMapPosVo.class);//一些实体类的get/set方法没有调用到，需要单独复制一下
        voPage.setRecords(voList);
        for (RobotMapPosVo vo : voList) {
            vo.setMapName(codeNameMap.get(vo.getMapCode()));
        }
        return R.ok(voPage);
    }


    @PostMapping("/list")
    @Operation(summary = "查询地图点位列表")
    public R<List<RobotMapPosVo>> list() {
        Map<String, String> codeNameMap = robotMapService.list().stream().collect(Collectors.toMap(RobotMap::getMapCode, RobotMap::getMapName));
        List<RobotMapPos> seqList = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().isNotNull(RobotMapPos::getSeq).orderByAsc(RobotMapPos::getSeq));
        List<RobotMapPos> noSeqList = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().isNull(RobotMapPos::getSeq));
        List<RobotMapPos> data = new ArrayList<>();
        data.addAll(seqList);
        data.addAll(noSeqList);
        List<RobotMapPosVo> voList = BeanUtil.copyToList(data, RobotMapPosVo.class);//一些实体类的get/set方法没有调用到，需要单独复制一下
        for (RobotMapPosVo vo : voList) {
            vo.setMapName(codeNameMap.get(vo.getMapCode()));
        }
        return R.ok(voList);
    }

    @PutMapping("sort")
    @Operation(summary = "设置巡检路线默认排序")
    public R sort(@RequestBody Long[] ids) {
        List<RobotMapPos> dbList = robotMapPosService.list();
        Map<Long, RobotMapPos> dbMap = dbList.stream().collect(Collectors.toMap(RobotMapPos::getId, obj -> obj));
        List<RobotMapPos> updateList = new ArrayList<>();
        for (int i = 0; i < ids.length; i++) {
            long id = ids[i];
            RobotMapPos pos = dbMap.get(id);
            if (pos==null){
                continue;
            }
            pos.setSeq(i);
            updateList.add(pos);
        }
        robotMapPosService.updateBatchById(updateList);
        return R.ok();
    }


    @PostMapping
    @Operation(summary = "添加地图点位")
    public R save(@RequestBody RobotMapPos robotMapPos) {
        //robotMapPos.setId(null);
        robotMapPosService.save(robotMapPos);
        if (StrUtil.isNotBlank(robotMapPos.getMapCode())){
            String currentMap = robotDriverService.getWebPos().getCurrentMap();
            if (robotMapPos.getMapCode().equals(currentMap)){
                RobotMap map = robotMapService.findByMapCode(currentMap);
                map.setPosList(robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(RobotMapPos::getMapCode, robotMapPos.getMapCode())));
                robotDriverService.selMap(map);
            }
        }
        return R.ok(robotMapPos);
    }

    @PutMapping
    @Operation(summary = "更新地图点位")
    public R update(@Valid @RequestBody RobotMapPos robotMapPos) {
        robotMapPosService.updateById(robotMapPos);
        if (StrUtil.isNotBlank(robotMapPos.getMapCode())){
            String currentMap = robotDriverService.getWebPos().getCurrentMap();
            if (robotMapPos.getMapCode().equals(currentMap)){
                RobotMap map = robotMapService.findByMapCode(currentMap);
                map.setPosList(robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().eq(RobotMapPos::getMapCode, robotMapPos.getMapCode())));
                robotDriverService.selMap(map);
            }
        }
        return R.ok(robotMapPos);
    }

    @GetMapping(value = "/{id}")
    @Operation(summary = "获取点位详情")
    public R<RobotMapPosVo> getDetail(@PathVariable Integer id) {
        RobotMapPos mapPos= robotMapPosService.getById(id);
        RobotMapPosVo vo= new RobotMapPosVo();
        BeanUtil.copyProperties(mapPos, vo);
        return R.ok(vo);
    }

    @Operation(summary = "通过id删除机器人地图坐标管理表" , description = "通过id删除机器人地图坐标管理表" )
    @DeleteMapping
    public R removeById(@RequestBody Integer[] ids) {
        return R.ok(robotMapPosService.removeBatchByIds(CollUtil.toList(ids)));
    }

    @GetMapping(value = "goStation")
    @Operation(summary = "前往站点")
    public R goStation(@RequestParam(value = "posId") Integer posId) {
        RobotMapPos robotMapPos = robotMapPosService.getById(posId);
        if(robotMapPos == null) {
            return R.failed("该点位已经被删除");
        }
        dispatchService.go2TargetPosition(robotMapPos, false);
        //robotDriverService.robotTaskGoTarget(
        //        RobotGoTargetPosDto.builder()
        //                .robot(robotService.getDefaultRobot())
        //                .code(robotMapPos.getCode())
        //                .charge(false).posId(posId)
        //                .taskId(UUID.randomUUID().toString().replace("-","")).build()
        //);
        return R.ok();
    }


    @Operation(summary = "通过id批量标定")
    @PostMapping("/batchCalibration")
    public R batchCalibration(@RequestBody Integer[] ids) {
        try {
            log.info("ids：{}", CollUtil.toList(ids));
            if (ids.length == 0) {
                return R.ok();
            }
            List<RobotMapPos> list = robotMapPosService.list(Wrappers.<RobotMapPos>lambdaQuery().in(RobotMapPos::getId, CollUtil.toList(ids)));
            return robotDriverService.executeOtherCommand(RobotOtherCommandEnum.BATCH_CALIBRATION, JSON.toJSONString(list));
        }catch (Exception e){
            return R.failed("请检查执行端与机器人是否正常通讯");
        }
    }

    @Operation(summary = "清空标定")
    @GetMapping("/clearCalibration")
    public R clearCalibration() {
        try {
            return robotDriverService.executeOtherCommand(RobotOtherCommandEnum.CLEAR_CALIBRATION, null);
        }catch (Exception e){
            return R.failed("请检查执行端与机器人是否正常通讯");
        }
    }

    @Operation(summary = "获取机器人当前位置数据")
    @GetMapping("/currentPosInfo")
    public R<PosMarkVo> getCurrentPosInfo() {
        try {
            IRobotPosDto webPos = robotDriverService.getWebPos();
            PosMarkVo vo= new PosMarkVo();
            vo.setPosX(webPos.getX());
            vo.setPosY(webPos.getY());
            vo.setPosZ(0.0D);
            vo.setYaw(webPos.getAngle());
            vo.setMapCode(webPos.getCurrentMap());
            vo.setLabel(webPos.getLabel());
            vo.setPixelX(webPos.getPixelX());
            vo.setPixelY(webPos.getPixelY());
            return R.ok(vo);
        }catch (Exception e){
            return R.failed("获取当前位置数据失败");
        }
    }

    @Operation(summary = "获取设备点位坐标")
    @GetMapping("/device")
    public R<List<RobotClientDevicePosDto>> device() {
        try {
            List<RobotClientDevicePosDto> list = new ArrayList<>();
            List<RobotMapPos> posList = robotMapPosService.list();
            for (RobotMapPos robotMapPos : posList) {
                RobotClientDevicePosDto dto = BeanUtil.copyProperties(robotMapPos, RobotClientDevicePosDto.class);
                list.add(dto);
            }
            return R.ok(list);
        }catch (Exception e){
            return R.failed("获取当前位置数据失败");
        }
    }


}
